﻿// <copyright file="TrackLocation.cs" company="Microsoft Corporation">
// Copyright (c) 2010 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2010-07-19</date>
// <summary>TrackLocation class definition</summary>

namespace Microsoft.WebAnalytics.Location
{
    using System;
    using System.ComponentModel.Composition;
    using System.Device.Location;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Interactivity;

    /// <summary>
    /// Track Geo coordinate "Locations" events when triggered
    /// </summary>
    /// <remarks>
    /// <list type="table">
    /// <item>
    /// <term>Platforms</term>
    /// <description>Windows Phone 7</description>
    /// </item>
    /// <item>
    /// <term>AnalyticsEvent.Name</term>
    /// <description>Location</description>
    /// </item>
    /// <item>
    /// <term>AnalyticsEvent.ActionValue</term>
    /// <description>{Latitude},{Longitude}</description>
    /// </item>
    /// <item>
    /// <term>Required Capabilities</term>
    /// <description>ID_CAP_NETWORKING, ID_CAP_LOCATION</description>
    /// </item>
    /// </list>
    /// </remarks>
    public class TrackLocation : TriggerAction<FrameworkElement>, IDisposable
    {
        #region Fields
        /// <summary>
        /// the geo coordinate watcher
        /// </summary>
        private GeoCoordinateWatcher watcher;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the TrackLocation class.
        /// </summary>
        public TrackLocation()
        {
            this.Accuracy = GeoPositionAccuracy.Default;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the position accuracy (default is Default)
        /// </summary>
        public GeoPositionAccuracy Accuracy { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to suppress the permission prompt
        /// </summary>
        public bool SuppressPermissionPrompt { get; set; }

        /// <summary>
        /// Gets or sets the Log Action 
        /// </summary>
        [Import("Log")]
        public Action<AnalyticsEvent> Log { get; set; }

        #endregion

        #region Methods
        /// <summary>
        /// Dispose the class
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);

            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// The trigger was invoked 
        /// </summary>
        /// <param name="parameter">the event parameter</param>
        protected override void Invoke(object parameter)
        {
            if (this.watcher.Status == GeoPositionStatus.Ready)
            {
                var logEvent = new AnalyticsEvent
                {
                    ActionValue = string.Format(
                        CultureInfo.InvariantCulture,
                        "{0},{1}",
                        this.watcher.Position.Location.Latitude,
                        this.watcher.Position.Location.Longitude),
                    Name = "Location",
                    ObjectType = this.watcher.GetType().Name,
                };

                this.Log(logEvent);
            }
        }

        /// <summary>
        /// Attach to the geo coordinate watcher
        /// </summary>
        protected override void OnAttached()
        {
            CompositionInitializerEx.SatisfyImports(this);

            base.OnAttached();

            this.watcher = new GeoCoordinateWatcher(this.Accuracy);

            this.watcher.Start(this.SuppressPermissionPrompt);

            this.AssociatedObject.Unloaded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
            {
                this.watcher.Stop();
            });
        }

        /// <summary>
        /// Detach from the watcher
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (this.watcher.Status == GeoPositionStatus.Ready)
            {
                this.watcher.Stop();
            }
        }

        /// <summary>
        /// Dispose of the watcher
        /// </summary>
        /// <param name="disposing">true if disposing</param>
        protected virtual void Dispose(bool disposing)
        {
            if (this.watcher != null)
            {
                this.watcher.Dispose();

                this.watcher = null;
            }
        }
        #endregion
    }
}
